#include <buola/gui/x11/auto.h>

#include <buola/gl.h>
#include <buola/gui/x11/cx11window.h>
#include <buola/gui/x11/cvisual.h>
#include <buola/gui/x11/cx11display.h>
#include <buola/gui/x11/cglxinterface.h>
#include <buola/gui/x11/cglxcontext.h>

namespace buola { namespace gui { namespace x11 {

CGLXContext *CGLXContext::mReferenceContext=nullptr;
CX11Window *CGLXContext::mFakeWindow=nullptr;

CGLXContext::CGLXContext(CX11Window *pWindow, bool pDirect)
    :   mWindow(pWindow)
    ,   mInterface(mWindow->GLXInterface())
{
    if(!mReferenceContext)
        mReferenceContext=new CGLXContext(nReferenceContext);

    DoCreateContext(mReferenceContext,pDirect);
}

CGLXContext::CGLXContext(NReferenceContext)
{
    mFakeWindow=new CX11Window(nullptr,get_default_x11_display());
    mFakeWindow->Create(nullptr,CPoint_d(0,0),CSize_d(1,1));
    mWindow=mFakeWindow;
    mInterface=mWindow->GLXInterface();

    DoCreateContext(nullptr,true);
}

CGLXContext::CGLXContext(NWithoutWindow)
{
    if(!mReferenceContext)
        mReferenceContext=new CGLXContext(nReferenceContext);

    mWindow=mFakeWindow;
    mInterface=mWindow->GLXInterface();

    DoCreateContext(mReferenceContext,true);
}

CGLXContext::~CGLXContext()
{
    glXDestroyContext(get_default_x11_display()->GetDisplay(),mContext);
}

void CGLXContext::DoCreateContext(CGLXContext *pReference,bool pDirect)
{
    int lAttribs[]={
        GLX_CONTEXT_MAJOR_VERSION_ARB, 3,
        GLX_CONTEXT_MINOR_VERSION_ARB, 2,
        GLX_CONTEXT_FLAGS_ARB        , GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB,
        GLX_CONTEXT_PROFILE_MASK_ARB , GLX_CONTEXT_CORE_PROFILE_BIT_ARB,
        0
    };

    mContext=glXCreateContextAttribsARB(get_default_x11_display()->GetDisplay(),mInterface->mFBConfig,
                                        pReference?mReferenceContext->mContext:nullptr,pDirect,lAttribs);
}

void CGLXContext::MakeCurrent(img::CSurface *pSurface)
{
    if(pSurface)
    {
        mWindow=dynamic_cast<CX11Window*>(pSurface);
        mInterface=mWindow->GLXInterface();
    }

    if(CGLX::GetVersion()>=GLX_SERVERVERSION(1,3))
    {
        glXMakeContextCurrent(get_default_x11_display()->GetDisplay(),mInterface->mDrawable,
                        mInterface->mDrawable,mContext);
    }
    else
    {
        glXMakeCurrent(get_default_x11_display()->GetDisplay(),mInterface->mDrawable,mContext);
    }
}

bool CGLXContext::IsCurrent()
{
    return (glXGetCurrentContext()==mContext);
}

void CGLXContext::SwapBuffers()
{
    glXSwapBuffers(get_default_x11_display()->GetDisplay(),mInterface->mDrawable);
}

/*namespace x11*/ } /*namespace gui*/ } /*namespace buola*/ }
